home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / bc-1_02.lha / bc-1.02 / bc.y < prev    next >
Text File  |  1992-03-04  |  15KB  |  613 lines

  1. %{
  2. /* bc.y: The grammar for a POSIX compatable bc processor with some
  3.          extensions to the language. */
  4.  
  5. /*  This file is part of bc written for MINIX.
  6.     Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  7.  
  8.     This program is free software; you can redistribute it and/or modify
  9.     it under the terms of the GNU General Public License as published by
  10.     the Free Software Foundation; either version 2 of the License , or
  11.     (at your option) any later version.
  12.  
  13.     This program is distributed in the hope that it will be useful,
  14.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.     GNU General Public License for more details.
  17.  
  18.     You should have received a copy of the GNU General Public License
  19.     along with this program; see the file COPYING.  If not, write to
  20.     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22.     You may contact the author by:
  23.        e-mail:  phil@cs.wwu.edu
  24.       us-mail:  Philip A. Nelson
  25.                 Computer Science Department, 9062
  26.                 Western Washington University
  27.                 Bellingham, WA 98226-9062
  28.        
  29. *************************************************************************/
  30.  
  31. #include "bcdefs.h"
  32. #include "global.h"
  33. #include "proto.h"
  34. %}
  35.  
  36. %start program
  37.  
  38. %union {
  39.     char     *s_value;
  40.     char      c_value;
  41.     int      i_value;
  42.     arg_list *a_value;
  43.        }
  44.  
  45. /* Extensions over POSIX bc.
  46.    a) NAME was LETTER.  This grammer allows longer names.
  47.       Single letter names will still work.
  48.    b) Relational_expression allowed only one comparison.
  49.       This grammar has added boolean expressions with
  50.       && (and) || (or) and ! (not) and allowed all of them in
  51.       full expressions.
  52.    c) Added an else to the if.
  53.    d) Call by variable array parameters
  54.    e) read() procedure that reads a number under program control from stdin.
  55.    f) halt statement that halts the the program under program control.  It
  56.       is an executed statement.
  57.    g) continue statement for for loops.
  58.    h) optional expressions in the for loop.
  59.    i) print statement to print multiple numbers per line.
  60.    j) warranty statement to print an extended warranty notice.
  61.    j) limits statement to print the processor's limits.
  62. */
  63.  
  64. %token <i_value> NEWLINE AND OR NOT
  65. %token <s_value> STRING NAME NUMBER
  66. /*     '-', '+' are tokens themselves        */
  67. %token <c_value> MUL_OP
  68. /*     '*', '/', '%'                 */
  69. %token <c_value> ASSIGN_OP
  70. /*     '=', '+=',  '-=', '*=', '/=', '%=', '^=' */
  71. %token <s_value> REL_OP
  72. /*     '==', '<=', '>=', '!=', '<', '>'     */
  73. %token <c_value> INCR_DECR
  74. /*     '++', '--'                 */
  75. %token <i_value> Define    Break    Quit    Length
  76. /*     'define', 'break', 'quit', 'length'     */
  77. %token <i_value> Return    For    If    While    Sqrt   Else
  78. /*     'return', 'for', 'if', 'while', 'sqrt', 'else'     */
  79. %token <i_value> Scale    Ibase    Obase    Auto  Read
  80. /*     'scale', 'ibase', 'obase', 'auto', 'read'     */
  81. %token <i_value> Warranty, Halt, Last, Continue, Print, Limits
  82. /*     'warranty', 'halt', 'last', 'continue', 'print', 'limits'   */
  83.  
  84. /* Types of all other things. */
  85. %type <i_value> expression return_expression named_expression opt_expression
  86. %type <c_value> '+' '-' 
  87. %type <a_value> opt_parameter_list opt_auto_define_list define_list
  88. %type <a_value> opt_argument_list argument_list
  89. %type <i_value> program input_item semicolon_list statement_list
  90. %type <i_value> statement function   statement_or_error
  91.  
  92. /* precedence */
  93. %left OR
  94. %left AND
  95. %nonassoc NOT
  96. %left REL_OP
  97. %right ASSIGN_OP
  98. %left '+' '-'
  99. %left MUL_OP
  100. %right '^'
  101. %nonassoc UNARY_MINUS
  102. %nonassoc INCR_DECR
  103.  
  104. %%
  105. program            : /* empty */
  106.                 {
  107.                   $$ = 0;
  108.                   if (interactive)
  109.                 {
  110.                   printf ("%s\n", BC_VERSION);
  111.                   welcome ();
  112.                 }
  113.                 }
  114.             | program input_item
  115.             ;
  116. input_item        : semicolon_list NEWLINE
  117.                 { run_code (); }
  118.             | function
  119.                 { run_code (); }
  120.             | error NEWLINE
  121.                 {
  122.                   yyerrok;
  123.                   init_gen ();
  124.                 }
  125.             ;
  126. semicolon_list        : /* empty */
  127.                 { $$ = 0; }
  128.             | statement_or_error
  129.             | semicolon_list ';' statement_or_error
  130.             | semicolon_list ';'
  131.             ;
  132. statement_list        : /* empty */
  133.                 { $$ = 0; }
  134.             | statement_or_error
  135.             | statement_list NEWLINE
  136.             | statement_list NEWLINE statement_or_error
  137.             | statement_list ';'
  138.             | statement_list ';' statement
  139.             ;
  140. statement_or_error    : statement
  141.               | error statement
  142.                 { $$ = $2; }
  143.             ;
  144. statement         : Warranty
  145.                 { warranty (""); }
  146.             | Limits
  147.                 { limits (); }
  148.             | expression
  149.                 {
  150.                   if ($1 & 2)
  151.                 warn ("comparison in expression");
  152.                   if ($1 & 1)
  153.                 generate ("W");
  154.                   else 
  155.                 generate ("p");
  156.                 }
  157.             | STRING
  158.                 {
  159.                   $$ = 0;
  160.                   generate ("w");
  161.                   generate ($1);
  162.                   free ($1);
  163.                 }
  164.             | Break
  165.                 {
  166.                   if (break_label == 0)
  167.                 yyerror ("Break outside a for/while");
  168.                   else
  169.                 {
  170.                   sprintf (genstr, "J%1d:", break_label);
  171.                   generate (genstr);
  172.                 }
  173.                 }
  174.             | Continue
  175.                 {
  176.                   warn ("Continue statement");
  177.                   if (continue_label == 0)
  178.                 yyerror ("Continue outside a for");
  179.                   else
  180.                 {
  181.                   sprintf (genstr, "J%1d:", continue_label);
  182.                   generate (genstr);
  183.                 }
  184.                 }
  185.             | Quit
  186.                 { exit (0); }
  187.             | Halt
  188.                 { generate ("h"); }
  189.             | Return
  190.                 { generate ("0R"); }
  191.             | Return '(' return_expression ')'
  192.                 { generate ("R"); }
  193.             | For 
  194.                 {
  195.                   $1 = break_label; 
  196.                   break_label = next_label++;
  197.                 }
  198.               '(' opt_expression ';'
  199.                 {
  200.                   if ($4 > 1)
  201.                 warn ("Comparison in first for expression");
  202.                   $4 = next_label++;
  203.                   if ($4 < 0)
  204.                 sprintf (genstr, "N%1d:", $4);
  205.                   else
  206.                 sprintf (genstr, "pN%1d:", $4);
  207.                   generate (genstr);
  208.                 }
  209.               opt_expression ';'
  210.                 {
  211.                   if ($7 < 0) generate ("1");
  212.                   $7 = next_label++;
  213.                   sprintf (genstr, "B%1d:J%1d:", $7, break_label);
  214.                   generate (genstr);
  215.                   $<i_value>$ = continue_label;
  216.                   continue_label = next_label++;
  217.                   sprintf (genstr, "N%1d:", continue_label);
  218.                   generate (genstr);
  219.                 }
  220.               opt_expression ')'
  221.                 {
  222.                   if ($10 > 1)
  223.                 warn ("Comparison in third for expression");
  224.                   if ($10 < 0)
  225.                 sprintf (genstr, "J%1d:N%1d:", $4, $7);
  226.                   else
  227.                 sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
  228.                   generate (genstr);
  229.                 }
  230.               statement
  231.                 {
  232.                   sprintf (genstr, "J%1d:N%1d:",
  233.                        continue_label, break_label);
  234.                   generate (genstr);
  235.                   break_label = $1;
  236.                   continue_label = $<i_value>9;
  237.                 }
  238.             | If '(' expression ')' 
  239.                 {
  240.                   $3 = if_label;
  241.                   if_label = next_label++;
  242.                   sprintf (genstr, "Z%1d:", if_label);
  243.                   generate (genstr);
  244.                 }
  245.               statement  opt_else
  246.                 {
  247.                   sprintf (genstr, "N%1d:", if_label); 
  248.                   generate (genstr);
  249.                   if_label = $3;
  250.                 }
  251.             | While 
  252.                 {
  253.                   $1 = next_label++;
  254.                   sprintf (genstr, "N%1d:", $1);
  255.                   generate (genstr);
  256.                 }
  257.             '(' expression 
  258.                 {
  259.                   $4 = break_label; 
  260.                   break_label = next_label++;
  261.                   sprintf (genstr, "Z%1d:", break_label);
  262.                   generate (genstr);
  263.                 }
  264.             ')' statement
  265.                 {
  266.                   sprintf (genstr, "J%1d:N%1d:", $1, break_label);
  267.                   generate (genstr);
  268.                   break_label = $4;
  269.                 }
  270.             | '{' statement_list '}'
  271.                 { $$ = 0; }
  272.             | Print
  273.                 {  warn ("print statement"); }
  274.               print_list
  275.             ;
  276. print_list        : print_element
  277.              | print_element ',' print_list
  278.             ;
  279. print_element        : STRING
  280.                 {
  281.                   generate ("O");
  282.                   generate ($1);
  283.                   free ($1);
  284.                 }
  285.             | expression
  286.                 { generate ("P"); }
  287.              ;
  288. opt_else        : /* nothing */
  289.             | Else 
  290.                 {
  291.                   warn ("else clause in if statement");
  292.                   $1 = next_label++;
  293.                   sprintf (genstr, "J%d:N%1d:", $1, if_label); 
  294.                   generate (genstr);
  295.                   if_label = $1;
  296.                 }
  297.               statement
  298. function         : Define NAME '(' opt_parameter_list ')' '{'
  299.               NEWLINE opt_auto_define_list 
  300.                 {
  301.                   /* Check auto list against parameter list? */
  302.                   check_params ($4,$8);
  303.                   sprintf (genstr, "F%d,%s.%s[", lookup($2,FUNCT), 
  304.                        arg_str ($4,TRUE), arg_str ($8,TRUE));
  305.                   generate (genstr);
  306.                   free_args ($4);
  307.                   free_args ($8);
  308.                   $1 = next_label;
  309.                   next_label = 0;
  310.                 }
  311.               statement_list NEWLINE '}'
  312.                 {
  313.                   generate ("0R]");
  314.                   next_label = $1;
  315.                 }
  316.             ;
  317. opt_parameter_list    : /* empty */ 
  318.                 { $$ = NULL; }
  319.             | define_list
  320.             ;
  321. opt_auto_define_list     : /* empty */ 
  322.                 { $$ = NULL; }
  323.             | Auto define_list NEWLINE
  324.                 { $$ = $2; } 
  325.             | Auto define_list ';'
  326.                 { $$ = $2; } 
  327.             ;
  328. define_list         : NAME
  329.                 { $$ = nextarg (NULL, lookup ($1,SIMPLE)); }
  330.             | NAME '[' ']'
  331.                 { $$ = nextarg (NULL, lookup ($1,ARRAY)); }
  332.             | define_list ',' NAME
  333.                 { $$ = nextarg ($1, lookup ($3,SIMPLE)); }
  334.             | define_list ',' NAME '[' ']'
  335.                 { $$ = nextarg ($1, lookup ($3,ARRAY)); }
  336.             ;
  337. opt_argument_list    : /* empty */
  338.                 { $$ = NULL; }
  339.             | argument_list
  340.             ;
  341. argument_list         : expression
  342.                 {
  343.                   if ($1 > 1) warn ("comparison in argument");
  344.                   $$ = nextarg (NULL,0);
  345.                 }
  346.             | NAME '[' ']'
  347.                 {
  348.                   sprintf (genstr, "K%d:", -lookup ($1,ARRAY));
  349.                   generate (genstr);
  350.                   $$ = nextarg (NULL,1);
  351.                 }
  352.             | argument_list ',' expression
  353.                 {
  354.                   if ($3 > 1) warn ("comparison in argument");
  355.                   $$ = nextarg ($1,0);
  356.                 }
  357.             | argument_list ',' NAME '[' ']'
  358.                 {
  359.                   sprintf (genstr, "K%d:", -lookup ($3,ARRAY));
  360.                   generate (genstr);
  361.                   $$ = nextarg ($1,1);
  362.                 }
  363.             ;
  364. opt_expression         : /* empty */
  365.                 {
  366.                   $$ = -1;
  367.                   warn ("Missing expression in for statement");
  368.                 }
  369.             | expression
  370.             ;
  371. return_expression    : /* empty */
  372.                 {
  373.                   $$ = 0;
  374.                   generate ("0");
  375.                 }
  376.             | expression
  377.                 {
  378.                   if ($1 > 1)
  379.                 warn ("comparison in return expresion");
  380.                 }
  381.             ;
  382. expression        :  named_expression ASSIGN_OP 
  383.                 {
  384.                   if ($2 != '=')
  385.                 {
  386.                   if ($1 < 0)
  387.                     sprintf (genstr, "DL%d:", -$1);
  388.                   else
  389.                     sprintf (genstr, "l%d:", $1);
  390.                   generate (genstr);
  391.                 }
  392.                 }
  393.               expression
  394.                 {
  395.                   if ($4 > 1) warn("comparison in assignment");
  396.                   if ($2 != '=')
  397.                 {
  398.                   sprintf (genstr, "%c", $2);
  399.                   generate (genstr);
  400.                 }
  401.                   if ($1 < 0)
  402.                 sprintf (genstr, "S%d:", -$1);
  403.                   else
  404.                 sprintf (genstr, "s%d:", $1);
  405.                   generate (genstr);
  406.                   $$ = 0;
  407.                 }
  408.             ;
  409.             | expression AND 
  410.                 {
  411.                   warn("&& operator");
  412.                   $2 = next_label++;
  413.                   sprintf (genstr, "DZ%d:p", $2);
  414.                   generate (genstr);
  415.                 }
  416.               expression
  417.                 {
  418.                   sprintf (genstr, "DZ%d:p1N%d:", $2, $2);
  419.                   generate (genstr);
  420.                   $$ = $1 | $4;
  421.                 }
  422.             | expression OR
  423.                 {
  424.                   warn("|| operator");
  425.                   $2 = next_label++;
  426.                   sprintf (genstr, "B%d:", $2);
  427.                   generate (genstr);
  428.                 }
  429.               expression
  430.                  {
  431.                   int tmplab;
  432.                   tmplab = next_label++;
  433.                   sprintf (genstr, "B%d:0J%d:N%d:1N%d:",
  434.                        $2, tmplab, $2, tmplab);
  435.                   generate (genstr);
  436.                   $$ = $1 | $4;
  437.                 }
  438.             | NOT expression
  439.                 {
  440.                   $$ = $2;
  441.                   warn("! operator");
  442.                   generate ("!");
  443.                 }
  444.             | expression REL_OP expression
  445.                 {
  446.                   $$ = 3;
  447.                   switch (*($2))
  448.                 {
  449.                 case '=':
  450.                   generate ("=");
  451.                   break;
  452.  
  453.                 case '!':
  454.                   generate ("#");
  455.                   break;
  456.  
  457.                 case '<':
  458.                   if ($2[1] == '=')
  459.                     generate ("{");
  460.                   else
  461.                     generate ("<");
  462.                   break;
  463.  
  464.                 case '>':
  465.                   if ($2[1] == '=')
  466.                     generate ("}");
  467.                   else
  468.                     generate (">");
  469.                   break;
  470.                 }
  471.                 }
  472.             | expression '+' expression
  473.                 {
  474.                   generate ("+");
  475.                   $$ = $1 | $3;
  476.                 }
  477.             | expression '-' expression
  478.                 {
  479.                   generate ("-");
  480.                   $$ = $1 | $3;
  481.                 }
  482.             | expression MUL_OP expression
  483.                 {
  484.                   genstr[0] = $2;
  485.                   genstr[1] = 0;
  486.                   generate (genstr);
  487.                   $$ = $1 | $3;
  488.                 }
  489.             | expression '^' expression
  490.                 {
  491.                   generate ("^");
  492.                   $$ = $1 | $3;
  493.                 }
  494.             | '-' expression  %prec UNARY_MINUS
  495.                 {
  496.                   generate ("n");
  497.                   $$ = $2;
  498.                 }
  499.             | named_expression
  500.                 {
  501.                   $$ = 1;
  502.                   if ($1 < 0)
  503.                 sprintf (genstr, "L%d:", -$1);
  504.                   else
  505.                 sprintf (genstr, "l%d:", $1);
  506.                   generate (genstr);
  507.                 }
  508.             | NUMBER
  509.                 {
  510.                   int len = strlen($1);
  511.                   $$ = 1;
  512.                   if (len == 1 && *$1 == '0')
  513.                 generate ("0");
  514.                   else if (len == 1 && *$1 == '1')
  515.                 generate ("1");
  516.                   else
  517.                 {
  518.                   generate ("K");
  519.                   generate ($1);
  520.                   generate (":");
  521.                 }
  522.                   free ($1);
  523.                 }
  524.             | '(' expression ')'
  525.                 { $$ = $2 | 1; }
  526.             | NAME '(' opt_argument_list ')'
  527.                 {
  528.                   $$ = 1;
  529.                   if ($3 != NULL)
  530.                 { 
  531.                   sprintf (genstr, "C%d,%s:",
  532.                        lookup ($1,FUNCT),
  533.                        arg_str ($3,FALSE));
  534.                   free_args ($3);
  535.                 }
  536.                   else
  537.                 {
  538.                   sprintf (genstr, "C%d:", lookup ($1,FUNCT));
  539.                 }
  540.                   generate (genstr);
  541.                 }
  542.             | INCR_DECR named_expression
  543.                 {
  544.                   $$ = 1;
  545.                   if ($2 < 0)
  546.                 {
  547.                   if ($1 == '+')
  548.                     sprintf (genstr, "DA%d:L%d:", -$2, -$2);
  549.                   else
  550.                     sprintf (genstr, "DM%d:L%d:", -$2, -$2);
  551.                 }
  552.                   else
  553.                 {
  554.                   if ($1 == '+')
  555.                     sprintf (genstr, "i%d:l%d:", $2, $2);
  556.                   else
  557.                     sprintf (genstr, "d%d:l%d:", $2, $2);
  558.                 }
  559.                   generate (genstr);
  560.                 }
  561.             | named_expression INCR_DECR
  562.                 {
  563.                   $$ = 1;
  564.                   if ($1 < 0)
  565.                 {
  566.                   sprintf (genstr, "DL%d:x", -$1);
  567.                   generate (genstr); 
  568.                   if ($2 == '+')
  569.                     sprintf (genstr, "A%d:", -$1);
  570.                   else
  571.                       sprintf (genstr, "M%d:", -$1);
  572.                 }
  573.                   else
  574.                 {
  575.                   sprintf (genstr, "l%d:", $1);
  576.                   generate (genstr);
  577.                   if ($2 == '+')
  578.                     sprintf (genstr, "i%d:", $1);
  579.                   else
  580.                     sprintf (genstr, "d%d:", $1);
  581.                 }
  582.                   generate (genstr);
  583.                 }
  584.             | Length '(' expression ')'
  585.                 { generate ("cL"); $$ = 1;}
  586.             | Sqrt '(' expression ')'
  587.                 { generate ("cR"); $$ = 1;}
  588.             | Scale '(' expression ')'
  589.                 { generate ("cS"); $$ = 1;}
  590.             | Read '(' ')'
  591.                 {
  592.                   warn ("read function");
  593.                   generate ("cI"); $$ = 1;
  594.                 }
  595.             ;
  596. named_expression    : NAME
  597.                 { $$ = lookup($1,SIMPLE); }
  598.             | NAME '[' expression ']'
  599.                 {
  600.                   if ($3 > 1) warn("comparison in subscript");
  601.                   $$ = lookup($1,ARRAY);
  602.                 }
  603.             | Ibase
  604.                 { $$ = 0; }
  605.             | Obase
  606.                 { $$ = 1; }
  607.             | Scale
  608.                 { $$ = 2; }
  609.             | Last
  610.                 { $$ = 3; }
  611.             ;
  612. %%
  613.